package de.koller.balance.scene.angryCube;

import de.koller.aframe.gl.AFrame;
import de.koller.aframe.gl.ATexture;
import de.koller.aframe.gl.BitmapTexture;
import de.koller.aframe.gl.Camera;
import de.koller.aframe.gl.Utils;
import de.koller.aframe.gl.obj.Quad;
import de.koller.altitude.render.textures.GridTexture;
import de.koller.balance.obj.FormableCube;
import de.koller.balance.render.BRenderExt;
import de.koller.oceanFramework.gl.util.ParticleTexture;
import de.koller.oceanFramework.gl.util.RasterManager;
import de.koller.oceanFramework.gl.util.ViewUtil;
import de.koller.oceanFramework.math.RVec3;
import de.koller.oceanFramework.util.ColorIntUtil;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

public class AngryCubeSceneHiRes extends BRenderExt {
	public final ATexture agrid = new GridTexture();
	public final BitmapTexture tex = new BitmapTexture( "de/koller/balance/scene/resource/textures.png" );
	
	public final BitmapTexture faceCuteTexture = new BitmapTexture( "de/koller/balance/scene/angrycube/faveInno.png" );
	public final BitmapTexture faceAngryTexture = new BitmapTexture( "de/koller/balance/scene/angrycube/faveAngry.png" );
	
	private final Quad quad = Quad.createZPlane( -12, 0, -10, 20, 20 );
	
	private final Quad faceCute = Quad.createXPlane( -.5f, .5f, .51f, 1, 1 );
	private final FormableCube cubeCute = new FormableCube();
	
	private final Quad faceAngry = Quad.createXPlane( -.5f, .5f, .51f, 1, 1 );
	private final FormableCube cubeAngry = new FormableCube();
	
	private AFrame tmpFrame;
	private ParticleTexture tmpTexture;
	private ParticleTexture tmpTexture2;
	
	public final Camera camera = new Camera();
	
	public AngryCubeSceneHiRes() {
		quad.setTextureLayout( 20, 20 );
	}

	@Override
	protected void init() {
		super.init();
		
		tmpFrame = new AFrame( screenW*aliasRes, screenH*aliasRes );
		tmpFrame.setUp();
		tmpTexture = ParticleTexture.generate( screenW*aliasRes, screenH*aliasRes );
		tmpTexture2 = ParticleTexture.generate( screenW*aliasRes, screenH*aliasRes );
		
//		BitmapTexture t = tex;
//		float k = t.tcoord( 63 );

//		System.arraycopy( new float[] {
//			0, 0,  0, k,  k, k,  k, 0
//		}, 0, faceCute.uv, 0, 8 );
		
//		float z = t.tcoord( 66 );
//		float kn = t.tcoord( 128 );
//		System.arraycopy( new float[] {
//			z, 0,  z, k,  kn, k,  kn, 0
//		}, 0, faceAngry.uv, 0, 8 );
	}

	
	private void renderCubes() {
		cuteCubeRender( false );
		angryCubeRender( false );
	}
	
	private void renderFaces() {
		cuteCubeRender( true );
		angryCubeRender( true );
	}
	
	private void renderFloor() {
		agrid.bindAnisotrophic();
		if( !renderLight ) GL11.glColor3f( .7f, .7f, .7f );
		if(  renderLight ) GL11.glColor3f( .7f, .7f, .7f );
		quad.renderStructure();
	}
	
	private void initCamera() {
		GL11.glDisable( GL11.GL_CULL_FACE );
		GL11.glClear( GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT );
		
		GL11.glMatrixMode( GL11.GL_PROJECTION );
		GL11.glLoadIdentity();

		if( subX == -1 && subY == -1 ) {
			GLU.gluPerspective( 45, (float)1920/(float)1080, 0.001f, 2000.0f );
		} else {
			GL11.glScalef( 4, 4, 1 );
			GL11.glTranslatef( -.5f*subX+.75f, subY*.50f-.75f, 0 );
			GLU.gluPerspective( 45, (float)1920/(float)1080, 0.001f, 2000.0f );
		}
		
		GL11.glMatrixMode( GL11.GL_MODELVIEW );
		GL11.glLoadIdentity();
		
	}
	
	private void sceneSetup() {
		initCamera();
		
		GL11.glPushMatrix();
		camera.position.set( -9, 1, 9 );
		camera.setLookAt( new RVec3( -8.5f, 0, 8 ) );
		camera.up.set( 0, 1, 0 );
		camera.transformGL();
	}
	
	private void sceneUnset() {
		GL11.glPopMatrix();
	}

	@Override
	public void renderSzene() {
		if( subX == -1 && subY == -1 )
			renderSzenePreview();
		else {
			if( renderLight )
				renderLight();
			else
				renderSzeneQuality();
		}
			
	}
	
	public void renderSzenePreview() {		
		sceneSetup();
		
		renderFloor();
		renderCubes();
		renderFaces();
		
		sceneUnset();
	}

	public void renderQ( boolean light ) {
		System.out.println( "Licht: " + light );
		
		tmpFrame.bind();
		
		sceneSetup();
		GL11.glPushMatrix();
		GL11.glScalef( 1, -1, 1 );
		renderCubes();
		if( !light ) renderFaces();
		GL11.glPopMatrix();
		sceneUnset();
		
		tmpFrame.unbind();
		
		System.out.println( "transfer mirrored" );
		tmpFrame.bindTexture();
		Utils.loadTextureData( tmpTexture );
		
		// mirror
		tmpFrame.bind();
		sceneSetup();
		renderFloor();
		sceneUnset();
		tmpFrame.unbind();
		
		System.out.println( "transfer floor" );
		
		tmpFrame.bindTexture();
		Utils.loadTextureData( tmpTexture2 );
		
		System.out.println( "combine mirrored floor" );
		overlayReflect( tmpTexture2, tmpTexture );
		tmpTexture.flush();
		
		System.out.println( "render over" );
		tmpFrame.bind();
		tmpFrame.frame.clearFBO( 0, 0, 0, 0 );
		sceneSetup();
		renderCubes();
		if( !light ) renderFaces();		
		sceneUnset();
		tmpFrame.unbind();
		
		System.out.println( "transfer over" );
		tmpFrame.bindTexture();
		Utils.loadTextureData( tmpTexture2 );
		

		frame.bind();
		
		GL11.glMatrixMode( GL11.GL_PROJECTION );
		GL11.glLoadIdentity();

		GL11.glOrtho( 0, screenW*aliasRes, screenH*aliasRes, 0, -1000, 1000 );
		
		GL11.glMatrixMode( GL11.GL_MODELVIEW );
		GL11.glLoadIdentity();
		
		//tmpTexture2.bind();
		//ViewUtil.draw2D( 0, 0, broot.render.screenW*3, broot.render.screenH*3, 1 );
		
		System.out.println( "combine all" );
		for( int x = 0; x < tmpTexture.getWidth(); x++ )
			for( int y = 0; y < tmpTexture.getHeight(); y++ )
				if( ColorIntUtil.getAValue( tmpTexture2.colorAt( x, y ) ) != 0 )
					tmpTexture.setPixel( tmpTexture2.colorAt( x, y ), x, y );
		
		tmpTexture.flush();
		tmpTexture.bind();
		
		GL11.glColor3f( 1, 1, 1 );
		ViewUtil.draw2D( 0, 0, screenW*aliasRes, screenH*aliasRes, 0 );
		
	}
	
	private void overlayReflect( RasterManager floor, RasterManager out ) {
		for( int x = 0; x < out.getWidth(); x++ )
			for( int y = 0; y < out.getHeight(); y++ ) {
				int a = (int)(ColorIntUtil.getAValue( out.colorAt( x, y ) ) * 0.25f);
				int r = (int)(ColorIntUtil.getRValue( out.colorAt( x, y ) ) * 0.25f);
				int g = (int)(ColorIntUtil.getGValue( out.colorAt( x, y ) ) * 0.25f);
				int b = (int)(ColorIntUtil.getBValue( out.colorAt( x, y ) ) * 0.25f);
				
				out.setPixel( ColorIntUtil.add( floor.colorAt( x, y ), ColorIntUtil.getIntColor( a, r, g, b ) ), x, y );
			}
		
	}
	
	public void renderSzeneQuality() {
		renderQ( false );
	}

	public void renderLight() {
		renderQ( true );
	}

	private void angryCubeRender( boolean face ) {
		GL11.glPushMatrix();
		GL11.glTranslatef( -8.2f, .25f, 8.3f );
		GL11.glScalef( .5f, .5f, .5f );
		GL11.glRotatef( -70, 0, 1, 0);
		
		if( !face ) {
			if( !renderLight ) GL11.glColor3f( 1, 0, 0 );
			if(  renderLight ) GL11.glColor3f( 1, 0, 0 );
			agrid.bindAnisotrophic();
			cubeAngry.render();
		} else {
			GL11.glColor3f( 1, 1, 1 );
			faceAngryTexture.bindAnisotrophic();
			faceAngry.renderStructure();
		}
		
		GL11.glPopMatrix();
	}

	private void cuteCubeRender( boolean face ) {
		GL11.glPushMatrix();
		GL11.glTranslatef( -9.0f, .15f, 7.8f );
		GL11.glScalef( .3f, .3f, .3f );
		GL11.glRotatef( 10, 0, 1, 0);
		
		if( !face ) {
			if( !renderLight ) GL11.glColor3f( 0, 1, 0 );
			if(  renderLight ) GL11.glColor3f( 0, 1, 0 );
			agrid.bindAnisotrophic();
			cubeCute.render();
		} else {
			GL11.glColor3f( 1, 1, 1 );
			//tex.bindAnisotrophic();
			faceCuteTexture.bindAnisotrophic();
			faceCute.renderStructure();
		}
		
		GL11.glPopMatrix();
	}
	
}
